home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / scheme / pcscheme / geneva / sources.exe / SOURCES / EDWIN / STRUCT.S < prev    next >
Encoding:
Text File  |  1993-06-15  |  14.3 KB  |  438 lines

  1. ;;;
  2. ;;;    Copyright (c) 1985 Massachusetts Institute of Technology
  3. ;;;
  4. ;;;    This material was developed by the Scheme project at the
  5. ;;;    Massachusetts Institute of Technology, Department of
  6. ;;;    Electrical Engineering and Computer Science.  Permission to
  7. ;;;    copy this software, to redistribute it, and to use it for any
  8. ;;;    purpose is granted, subject to the following restrictions and
  9. ;;;    understandings.
  10. ;;;
  11. ;;;    1. Any copy made of this software must include this copyright
  12. ;;;    notice in full.
  13. ;;;
  14. ;;;    2. Users of this software agree to make their best efforts (a)
  15. ;;;    to return to the MIT Scheme project any improvements or
  16. ;;;    extensions that they make, so that these may be included in
  17. ;;;    future releases; and (b) to inform MIT of noteworthy uses of
  18. ;;;    this software.
  19. ;;;
  20. ;;;    3.  All materials developed as a consequence of the use of
  21. ;;;    this software shall duly acknowledge such use, in accordance
  22. ;;;    with the usual standards of acknowledging credit in academic
  23. ;;;    research.
  24. ;;;
  25. ;;;    4. MIT has made no warrantee or representation that the
  26. ;;;    operation of this software will be error-free, and MIT is
  27. ;;;    under no obligation to provide any services, by way of
  28. ;;;    maintenance, update, or otherwise.
  29. ;;;
  30. ;;;    5.  In conjunction with products arising from the use of this
  31. ;;;    material, there shall be no use of the name of the
  32. ;;;    Massachusetts Institute of Technology nor of any adaptation
  33. ;;;    thereof in any advertising, promotional, or sales literature
  34. ;;;    without prior written consent from MIT in each case.
  35. ;;;
  36. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  37. ;;;
  38. ;;;     Modified by Texas Instruments Inc 8/15/85
  39. ;;;
  40. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  41.  
  42. (begin
  43. (define-integrable %make-region
  44.   (lambda (start end)
  45.     (cons start end)))
  46.  
  47. (define-integrable region-start
  48.   (lambda (region)
  49.     (car region)))
  50.  
  51. (define-integrable region-end
  52.   (lambda (region)
  53.     (cdr region)))
  54.  
  55. (define-integrable region-group
  56.   (lambda (region)
  57.     (mark-group (region-start region))))
  58.  
  59. (define-integrable components->region
  60.   (lambda (start-line start-pos end-line end-pos)
  61.     (%make-region (mark-permanent! (%make-mark start-line start-pos #F))
  62.               (mark-permanent! (%make-mark end-line end-pos #T)))))
  63.  
  64. (define-integrable make-mark
  65.   (lambda (line position)
  66.     (%make-mark line position #T)))
  67.  
  68. (define-integrable %make-mark
  69.   (lambda (line position left-inserting?)
  70.     (let ((mark (make-vector 3)))
  71.       (vector-set! mark 0 line)
  72.       (vector-set! mark 1 position)
  73.       (vector-set! mark 2 left-inserting?)
  74.       mark)))
  75.  
  76. (define-integrable mark-line
  77.   (lambda (mark)
  78.     (vector-ref mark 0)))
  79.  
  80. (define-integrable %set-mark-line!
  81.   (lambda (mark line)
  82.     (vector-set! mark 0 line)))
  83.  
  84. (define-integrable mark-position
  85.   (lambda (mark)
  86.     (vector-ref mark 1)))
  87.  
  88. (define-integrable set-mark-position!
  89.   (lambda (mark position)
  90.     (vector-set! mark 1 position)))
  91.  
  92. (define-integrable mark-left-inserting?
  93.   (lambda (mark)
  94.     (vector-ref mark 2)))
  95.  
  96. (define-integrable mark-group
  97.   (lambda (mark)
  98.     (line-group (mark-line mark))))
  99.  
  100. (define-integrable line-tag 'line)
  101.  
  102. (define-integrable make-line
  103.   (lambda (string)
  104.     (let ((line (make-vector 8)))
  105.       (vector-set! line 3 line-tag)
  106.       (vector-set! line 1 string)
  107.       line)))
  108.  
  109. (define-integrable line-string
  110.   (lambda (line)
  111.     (vector-ref line 1)))
  112.  
  113. (define-integrable line-previous
  114.   (lambda (line)
  115.     (vector-ref line 2)))
  116.  
  117. (define-integrable line-next
  118.   (lambda (line)
  119.     (vector-ref line 0)))
  120.  
  121. (define-integrable line-marks
  122.   (lambda (line)
  123.     (vector-ref line 4)))
  124.  
  125. (define-integrable set-line-marks!
  126.   (lambda (line marks)
  127.     (vector-set! line 4 marks)))
  128.  
  129. (define-integrable line-group
  130.   (lambda (line)
  131.     (vector-ref line 5)))
  132.  
  133. (define-integrable set-line-group!
  134.   (lambda (line group)
  135.     (vector-set! line 5 group)))
  136.  
  137. (define-integrable line-number
  138.   (lambda (line)
  139.     (vector-ref line 6)))
  140.  
  141. (define-integrable set-line-number!
  142.   (lambda (line number)
  143.     (vector-set! line 6 number)))
  144.  
  145. (define-integrable line-alist
  146.   (lambda (line)
  147.     (vector-ref line 7)))
  148.  
  149. (define-integrable set-line-alist!
  150.   (lambda (line alist)
  151.   (vector-set! line 7 alist)))
  152. )
  153. ;;;; Text Data Structures
  154.  
  155. ;;; This file describes the data structures used to represent and
  156. ;;; manipulate text within the editor.
  157.  
  158. ;;; The basic unit of text is the GROUP, which is essentially a type
  159. ;;; of character string with some special operations.  Normally a
  160. ;;; group is modified by side effect; unlike character strings, groups
  161. ;;; will grow and shrink appropriately under such operations.  Also,
  162. ;;; it is possible to have pointers into a group, called MARKs, which
  163. ;;; continue to point to the "same place" under these operations; this
  164. ;;; would not be true of a string, elements of which are pointed at by
  165. ;;; indices.
  166.  
  167. ;;; As is stressed in the EMACS manual, marks point between characters
  168. ;;; rather than directly at them.  This perhaps counter-intuitive
  169. ;;; concept may aid understanding.
  170.  
  171. ;;; Besides acting as pointers into a group, marks may be compared.
  172. ;;; All of the marks within a group are totally ordered, and the
  173. ;;; standard order predicates are supplied for them.  In addition,
  174. ;;; marks in different groups are unordered with respect to one
  175. ;;; another.  The standard predicates have been extended to be false
  176. ;;; in this case, and another predicate, which indicates whether they
  177. ;;; are related, is supplied.
  178.  
  179. ;;; Marks may be paired into units called REGIONs.  Each region has a
  180. ;;; START mark and an END mark, and it must be the case that START is
  181. ;;; less than or equal to END in the mark ordering.  While in one
  182. ;;; sense this pairing of marks is trivial, it can also be used to
  183. ;;; reduce overhead in the implementation since a region guarantees
  184. ;;; that its marks satisfy this very basic relation.
  185.  
  186. ;;; As in most other editors of this type, there is a distinction
  187. ;;; between "temporary" and "permanent" marks.  The purpose for this
  188. ;;; distinction is that temporary marks require less overhead to
  189. ;;; create.  Conversely, temporary marks do not remain valid when
  190. ;;; their group is modified.  They are intended for local use when it
  191. ;;; is known that the group will remain unchanged.
  192.  
  193. ;;; The implementation of marks is different from previous
  194. ;;; implementations.  In particular, it is not possible to tell
  195. ;;; whether a mark is temporary or permanent.  Instead, a "caller
  196. ;;; saves"-like convention is used.  Whenever any given mark needs to
  197. ;;; be permanent, one merely calls a procedure which "permanentizes"
  198. ;;; it.  All marks are created temporary by default.
  199.  
  200. ;;; Internally, groups are represented as an ordered set of objects,
  201. ;;; called LINEs, which are doubly linked to form a linear chain.
  202. ;;; Each line represents a string of characters without newlines, and
  203. ;;; two adjacent lines are separated by a "virtual newline".  Thus
  204. ;;; this data structure directly corresponds to our intuitive concept
  205. ;;; of "line".
  206.  
  207. ;;; In some sense the choice of lines are the unit of text is quite
  208. ;;; arbitrary; there are no real technical benefits to be gained from
  209. ;;; the choice.  The decision to structure things this way was based
  210. ;;; on the fact that most current editors are built that way, and
  211. ;;; expediency demands that we not innovate too much.
  212.  
  213. ;;; With that said, it is important to restate that lines are an
  214. ;;; INTERNAL data representation.  Since the choice is arbitrary, they
  215. ;;; are not supported by any public operations.
  216.  
  217. ;;;; Groups
  218.  
  219. ;;; Every line belongs to a unique group, and every line belonging to
  220. ;;; the same group is related.  That is, the lines in a group are
  221. ;;; totally ordered.  Lines in different groups have no relation.
  222.  
  223. ;;; There is no sharing of lines between groups.  When lines are
  224. ;;; copied out of a group, they form a new group.  When they are
  225. ;;; inserted into a group, they become part of that group.
  226.  
  227. (define make-group)
  228. (let ()
  229.  
  230. (define group-tag 'group)
  231.  
  232. (set! make-group
  233. (named-lambda (make-group region)
  234.   (let ((group (make-vector 6)))
  235.     (vector-set! group 2 group-tag)
  236.     (vector-set! group 1 region)
  237.     (vector-set! group 0 region)
  238.     (vector-set! group 5 #F)
  239.     group)))
  240.  
  241. )
  242. (begin
  243. (define-integrable group-index:total-region 1)
  244. (define-integrable group-index:region 0)
  245. (define-integrable group-index:delete-daemons 3)
  246. (define-integrable group-index:insert-daemons 4)
  247. (define-integrable group-index:read-only-flag 5)
  248.  
  249. (define-integrable group-region
  250.   (lambda (group)
  251.     (vector-ref group group-index:region)))
  252.  
  253. (define (%set-group-region! group region)
  254.   (vector-set! group group-index:total-region region)
  255.   (vector-set! group group-index:region region))
  256.  
  257. (define-integrable %group-start
  258.   (lambda (group)
  259.     (region-start (group-region group))))
  260.  
  261. (define-integrable %group-end
  262.   (lambda (group)
  263.     (region-end (group-region group))))
  264. )
  265.  
  266. (define (group-read-only? group)
  267.   (vector-ref group group-index:read-only-flag))
  268.  
  269. (define (set-group-read-only! group)
  270.   (vector-set! group group-index:read-only-flag #T))
  271.  
  272. (define (set-group-writeable! group)
  273.   (vector-set! group group-index:read-only-flag #F))
  274.  
  275.  
  276. ;;;; Group Modification Daemons
  277.  
  278. (define (group-delete-daemons group)
  279.   (vector-ref group group-index:delete-daemons))
  280.  
  281. (define (add-group-delete-daemon! group daemon)
  282.   (vector-set! group group-index:delete-daemons
  283.            (cons daemon (vector-ref group group-index:delete-daemons))))
  284.  
  285. (define (region-delete-starting! region)
  286.   (if (group-read-only? (region-group region))
  287.       (editor-error "Trying to modify read only text."))
  288.   (region-modification-starting! (group-delete-daemons (region-group region))
  289.                  region))
  290.  
  291. (define (group-insert-daemons group)
  292.   (vector-ref group group-index:insert-daemons))
  293.  
  294. (define (add-group-insert-daemon! group daemon)
  295.   (vector-set! group group-index:insert-daemons
  296.            (cons daemon (vector-ref group group-index:insert-daemons))))
  297.  
  298. (define (region-insert-starting! mark)
  299.   (if (group-read-only? (mark-group mark))
  300.       (editor-error "Trying to modified read only text."))
  301.   (region-modification-starting! (group-insert-daemons (mark-group mark))
  302.                  mark))
  303.  
  304. (define (region-modification-starting! all-daemons argument)
  305.   (define (loop daemons)
  306.     (if (null? daemons)
  307.     '()
  308.     (let ((sync ((car daemons) argument)))
  309.       (if sync
  310.           (cons sync (loop (cdr daemons)))
  311.           (loop (cdr daemons))))))
  312.   (sync-daemons (loop all-daemons)))
  313.  
  314. (define ((sync-daemons daemons) region)
  315.   (define (loop daemons)
  316.     (if (not (null? daemons))
  317.     (begin ((car daemons) region)
  318.            (loop (cdr daemons)))))
  319.   (loop daemons))
  320.  
  321. ;;;; Regions
  322.  
  323. (define (make-region start end)
  324.   (cond ((mark<= start end) (%make-region start end))
  325.     ((mark<= end start) (%make-region end start))
  326.     (else (error "Marks not related" start end))))
  327.  
  328. (define (lines->region start-line end-line)
  329.   (let ((region (components->region start-line 0
  330.                     end-line (line-length end-line))))
  331.     (set-line-group! start-line (make-group region))
  332.     (number-lines! start-line end-line)
  333.     region))
  334.  
  335. (define (region-components region receiver)
  336.   (receiver (mark-line (region-start region))
  337.         (mark-position (region-start region))
  338.         (mark-line (region-end region))
  339.         (mark-position (region-end region))))
  340.  
  341. ;;;; Marks
  342.  
  343. (define (mark-components mark receiver)
  344.   (receiver (mark-line mark)
  345.         (mark-position mark)))
  346.  
  347. (define (mark-right-inserting mark)
  348.   (mark-permanent!
  349.    (if (mark-left-inserting? mark)
  350.        (%make-mark (mark-line mark) (mark-position mark) #F)
  351.        mark)))
  352.  
  353. (define (mark-left-inserting mark)
  354.   (mark-permanent!
  355.    (if (mark-left-inserting? mark)
  356.        mark
  357.        (%make-mark (mark-line mark) (mark-position mark) #T))))
  358.  
  359.  
  360. ;;;; Lines
  361.  
  362. ;;; Instead of using VECTOR, MAKE-LINE is coded in a strange way to
  363. ;;; make it maximally fast.  Both LIST->VECTOR and CONS are
  364. ;;; primitives.  Also, VECTOR would cons a list, then vectorize it,
  365. ;;; creating a bunch of garbage, while this only makes one cons.
  366.  
  367. (define (set-line-string! line string)
  368.   (vector-set! line 1 string)
  369.   (set-line-alist! line '()))
  370.  
  371. (define (connect-lines! previous next)
  372.   (if (not (null? previous)) (vector-set! previous 0 next))
  373.   (if (not (null? next)) (vector-set! next 2 previous)))
  374.  
  375. (define (disconnect-lines! start end)
  376.   (vector-set! start 2 '())
  377.   (vector-set! end 0 '()))
  378.  
  379.  
  380. ;;; line-length clashes with a scheme-primitive. we have defined
  381. ;;; a macro line-length which will replace all occurrences of line-length
  382. ;;; to line-string-length. Maybe, we will change it all ove the source
  383. ;;; someday. The macro will be present only while compiling Edwin
  384. ;;; sources.
  385.  
  386. ;;; (define-integrable (line-length line)
  387. ;;;  (string-length (line-string line)))
  388.  
  389. ;;;; Line Numbering
  390.  
  391. (define line-number-increment 256)
  392.  
  393. (define (number-lines! start-line end-line)
  394.   (define (number-upward group base increment)
  395.     (define (loop line number)
  396.       (set-line-group! line group)
  397.       (set-line-number! line number)
  398.       (if (not (eq? line end-line))
  399.       (loop (line-next line) (+ number increment))))
  400.     (loop start-line (+ base increment)))
  401.  
  402.   (define (number-downward group base increment)
  403.     (define (loop line number)
  404.       (set-line-group! line group)
  405.       (set-line-number! line number)
  406.       (if (not (eq? line start-line))
  407.       (loop (line-previous line) (- number increment))))
  408.     (loop end-line (- base increment)))
  409.  
  410.   (define (count-lines)
  411.     (define (loop line n)
  412.       (if (eq? line end-line)
  413.       n
  414.       (loop (line-next line) (1+ n))))
  415.     (loop start-line 1))
  416.  
  417.   (let ((lower-limit (line-previous start-line))
  418.     (upper-limit (line-next end-line)))
  419.     (if (null? lower-limit)
  420.     (if (null? upper-limit)
  421.         ;; Numbering entire group.  The first line
  422.         ;; had better be initialized correctly.
  423.         (number-upward (line-group start-line)
  424.                0
  425.                line-number-increment)
  426.         (number-downward (line-group upper-limit)
  427.                  (line-number upper-limit)
  428.                  line-number-increment))
  429.     (if (null? upper-limit)
  430.         (number-upward (line-group lower-limit)
  431.                (line-number lower-limit)
  432.                line-number-increment)
  433.         (number-upward (line-group lower-limit)
  434.                (line-number lower-limit)
  435.                (/ (- (line-number upper-limit)
  436.                  (line-number lower-limit))
  437.                   (1+ (count-lines))))))))
  438.